package spasticinvadoors;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.util.*;
import javax.swing.JOptionPane;

/**
 *
 * @author Mikael, Aron, Rikard och Magnus
 */
public class GameWindow{
    //klassvariabler
    
    public static final int fromtop = 48;
    public static final int space = 8;
    public static final int width = 640;
    public static final int height = 480;
    public static final int shieldY = 384;
    public boolean alive = true;
    public boolean success = true;
    public long lastFire = 0;
    public long lastMove = 0;
    public int speed = 8; //kan sätta lägre för svårighetsgrad (vid vinst)
    public int tempScore = 0;
        public int score = 0;
    public String scoretext;
    public long delayFire = 200;
    public long delayNpcFire = 1100;
    public int level = 1;
    public int pointsToAdd = 50;

    public int tempShotsFired = 0;
        public int shotsFired = 0;
    public int tempKills = 0;
        public int kills = 0;

    Random Generator = new Random();
        public ArrayList<Alien> Aliens = new ArrayList<Alien>();
        public ArrayList<Alien> livingAliens;
        public Ship ship = new Ship(296, 452);
        public ArrayList<Shield> Shields = new ArrayList<Shield>();
        public ArrayList<Shield> livingShields;
        public ArrayList<Bullet> Bullets = new ArrayList<Bullet>();
        public ArrayList<Bullet> livingBullets;

        public long prevBomb = -1;
        public JFrame window;

        public GameWindow() throws InterruptedException{
            //Skapa en ram, sätt storlek, sätt synlighet, blockera skalning
            window = new JFrame("Spastic Invadoors");
            window.setBounds(0, 0, width, height);
            window.setVisible(true);
            window.setResizable(false);
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //Main.echo("GameWindow");
            Thread.sleep(100);
            
            run();
            //Main.echo("run stopped");
        }
   


        public void run() throws InterruptedException{
                KeyListener kl = new KeyListener();
                window.addKeyListener(kl);

            Aliens = newAlienList();
            Shields = newShieldList();
                livingAliens = Aliens;
                livingBullets = Bullets;
                livingBullets.clear();
                livingShields = Shields;
                Graphics gw = window.getGraphics();
                
                while(alive){
                    Aliens = (ArrayList<Alien>)livingAliens.clone();
                    Bullets = (ArrayList<Bullet>)livingBullets.clone();
                    Shields = (ArrayList<Shield>)livingShields.clone();

                    BufferedImage img = new BufferedImage(width, height, 1);
                    Graphics g = img.getGraphics();
                    Graphics hud = img.getGraphics();
                    g.setColor(Color.black);
                    g.fillRect(0, 0, width, height);
                    
                    hud.setColor(Color.white);
	            scoretext = "Level: " + Integer.toString(level) + " | Score: " + Integer.toString(tempScore);
	            hud.drawString(scoretext, 320, 36);
                 


                    drawShip(g);
                    drawShields(g);

                        if(!Aliens.isEmpty()){
                            if(System.currentTimeMillis() > lastMove + speed){
                                moveAliens();
                                lastMove = System.currentTimeMillis();
                            }

                            drawAliens(g);
                            
                        }
                        else{
                            alive = false;
                            success = true;
                        }
                        if(!Bullets.isEmpty()){
                            moveBullets();
                            if(!Bullets.isEmpty()){
                            drawBullets(g);
                            }
                        }

                        
                    
                    
                        if(kl.fire && System.currentTimeMillis() > lastFire + delayFire){
                            fire(ship.position.getX(), ship.position.getY() - 24, true);
                            tempShotsFired++;
                            lastFire = System.currentTimeMillis();
                        }
                    if(kl.left)
                        if(ship.position.getX() >= 4)
                            ship.position.setX(ship.position.getX()-5);
                    if(kl.right)
                        if(ship.position.getX() <= 612)
                            ship.position.setX(ship.position.getX()+5);


                    if(prevBomb + delayNpcFire < (System.currentTimeMillis()) && (livingAliens.size() > 0)){
                            npcFire();
                            prevBomb = System.currentTimeMillis();
                        }

                    gw.drawImage(img, 0, 0, null);
                    // Om vinst/förlust, draw tempKillscreen, skicka upp box som kan starta om (måste göras u rmain då gamewindow har kvar alla variabler? eller resetta allt ihop)
                }
                if(success == false){
                    int f_reply = JOptionPane.showConfirmDialog(null, "You have lost. \n You had a score of " + tempScore + " but don't get too excited, you obviously suck... \n replay level?", "Window of failure", JOptionPane.YES_NO_OPTION);
                    if (f_reply == JOptionPane.YES_OPTION){
                        alive = true;
                        Bullets.clear();
                        ship.position.setX(320);
                        tempScore = score;
                        if(level == 1){
                            tempKills = 0;
                            tempScore = 0;
                        }
                        score = score - 500;
                        tempScore = score - 500;
                        //System.out.println("Starting over");
                        
                        run();
                    }
                    else{
                        System.exit(0);
                    }
                }
                else{
                    String dialog = "Level " + level + " cleared! \n You have a score of " + tempScore + " points \n Tot. Kills: " + tempKills + " Tot. Shots: " + tempShotsFired + "\n Proceed?";
                    int t_reply = JOptionPane.showConfirmDialog(null, dialog, "Window of great success", JOptionPane.YES_NO_OPTION);
                        if(t_reply == JOptionPane.YES_OPTION){
                            //if(speed > 0){
                                //speed--;
                            //}
                            
                            if(delayNpcFire > 0){
                                delayNpcFire -= 150;
                            }
                            delayFire += 40;
                            level++;
                            alive = true;
                            kills = tempKills;
                            shotsFired = tempShotsFired;
                            score = tempScore;
                            ship.position.setX(308);
                            pointsToAdd += 25;
                            run();
                        }
                        else{
                            System.exit(0);
                        }

                }

                

        }

        public void moveAliens(){
        boolean down = false;
            if(anyAtBorder()){
                switchDirection();
                down = true;
            }

            for(Alien a : Aliens){
                if(a.getDirection()){
                    a.position.setX(a.position.getX() + 4);
                }
                else if(!a.getDirection()){
                    a.position.setX(a.position.getX() - 4);
                }
                if(Shields.size() > 0){
                    if(a.position.getY() >= Shields.get(0).position.getY() - 23){ //Om en enda pixel av aliens är inne på shields område
                    alive = false;
                    success = false;
                    }
                }
                else{
                    if(a.position.getY() >= height - 40){
                        alive = false;
                        success = false;
                    }
                }
                if(down){
                    a.position.setY(a.position.getY() + 16);
                }
            }
            

            // direction påverkar hurvida vi ändrar position positivt eller negativt
            
        }

        public boolean anyAtBorder(){
            
            for(Alien a : Aliens){
                if(a.atBorder()){
                    return true;
                }
            }
            return false;
        }

        public void switchDirection(){
            for(Alien a : Aliens){
                a.setDirection(!a.getDirection());
            }
        }
        

        public void drawAliens(Graphics g){
            
            for(Alien a : Aliens){
                a.paint(g);
            }
        }
        public void drawShields(Graphics g){

            for(Shield s : Shields){
                s.paint(g);
            }
        }  

        public void drawShip (Graphics g){
            ship.paint(g);
        }

        public ArrayList<Alien> newAlienList(){
            ArrayList<Alien> list = new ArrayList<Alien>();
            for(int i=0;i<3;i++){
                for(int j = 0; j < 12; j++){
                    list.add(new Alien(nXPos(j), fromtop+i*24));
                    //Main.echo("Alien added to list");
                }
            }
        return list;
        }

        public ArrayList<Shield> newShieldList(){
            ArrayList<Shield> list = new ArrayList<Shield>();

            for(int i = 0; i < 6; i++){
                list.add(new Shield(nXPos(i*3) + 48, shieldY));
                //Main.echo("Shield added to list");
            }
        return list;
        }
        

        public int nXPos(int i){ // räknar ut hur många pixlar från kanten alien(i) behöver placeras
        int nPos = space+(space*i)+(24*i);
            return nPos;
        }

        public void drawBullets(Graphics g){
            for(Bullet b : Bullets){
                b.paint(g);
            //Main.echo("bullet drawn");
            }
        }

        public void fire(int x, int y, boolean dir){
            livingBullets.add(new Bullet(x, y, dir));
            //Main.echo("bullet added to list");
        }

        public void moveBullets(){
            int nb = 0;
            for(Bullet b : Bullets){

                if(b.position.getY() > 480){
                    killBullet(Bullets.indexOf(b));

                }
                else if(b.position.getY() < 0){
                    killBullet(Bullets.indexOf(b));
                }
                else{
                
                if(b.getDirection()){
                    b.position.setY(b.position.getY() - 6);
                }
                else{
                    b.position.setY(b.position.getY() + 6);
                }
                
                int na = 0;
                int nbOld = -1;
                for(Alien a: Aliens){
                    if((((b.position.getY()) > (a.position.getY() -21)) &&
                            ((b.position.getY()) < (a.position.getY() + 21)) &&
                            ((b.position.getX()) > (a.position.getX() - 21)) &&
                            ((b.position.getX()) < (a.position.getX() + 21))) && (b.getDirection())){
                                //System.out.println("hit!");
                            na = Aliens.indexOf(a);
                            nb = Bullets.indexOf(b);
                            //System.out.println("bullet" + nb + " has hit alien " + na);
                                if(nb == nbOld){
                                    na = na-1;
                                }
                            hit(na, nb);
                                nbOld = nb;
                            //System.out.println("hit finished!");
                            // na++ ger inte den verkliga positionen i listan
                            
                    }
                }
                if(Shields.size() > 0){
                    for(Shield s : Shields){
                    if(((b.position.getY()) > (s.position.getY() -22)) &&
                            ((b.position.getY()) < (s.position.getY() + 22)) &&
                            ((b.position.getX()) > (s.position.getX() - 22)) &&
                            ((b.position.getX()) < (s.position.getX() + 22))){
                                //System.out.println("Chuck Norris");
                             nb = Bullets.indexOf(b);
                            killBullet(nb);
                            livingShields.remove(s);
                            //System.out.println("Chuck Norris finished!");
                    }
                }
                }
                


                 if ((b.position.getY()) > (ship.position.getY()-15)   &&
                    ((b.position.getY()) < (ship.position.getY() +15)) &&
                    ((b.position.getX()) > (ship.position.getX() -15)) &&
                    ((b.position.getX()) < (ship.position.getX() +15)))
                        {
                        alive=false;
                        success=false;
                        }
            }
            }

        }

        public void npcFire(){
            ArrayList<Alien> Bombers = new ArrayList<Alien>();
            for(Alien a : Aliens){
                boolean valid = true;
                    for(Alien n : Aliens){
                        if(((n.position.getY() == a.position.getY() + 24) || (n.position.getY() == a.position.getY() + 48)) &&  n.position.getX() == a.position.getX()){
                            valid = false;
                        }

                    }
                if(valid){
                    Bombers.add(a);
                }
            }
            int Bomber = Generator.nextInt(Bombers.size());
            fire(Bombers.get(Bomber).position.getX(), Bombers.get(Bomber).position.getY() + 24, false);
        }


        public void hit(int na, int nb){
            // ut med två nya listor som ersätter de gamla i början på nästa iteration av run()
            //System.out.println("Call to remove alien:" + na);
            killAlien(na);
            //System.out.println("Call to remove bullet:" + nb);
            killBullet(nb);
        }

        public void killAlien(int na){
            try{
            livingAliens.remove(na);
            tempScore += pointsToAdd;
                tempKills++;
            }
            catch(IndexOutOfBoundsException e){
                System.out.println("IOOBE e");
            }
        }

        public void killBullet(int nb){
            try{
            livingBullets.remove(nb);
            }
            catch(IndexOutOfBoundsException e){
                System.out.println("IOOBE e");
            }
        }

}
